package com.mall.user.services;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.mall.commons.tool.exception.ValidateException;
import com.mall.user.util.IJwtTokenUtils;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.utils.AESUtil;
import lombok.Builder;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.joda.time.DateTime;
import org.springframework.stereotype.Component;

/**
 * create by ciggar on 2020/04/08
 */
@Slf4j
@Builder
@Service(interfaceClass = IJwtTokenUtils.class)
@Component
public class JwtTokenServiceImpl implements IJwtTokenUtils {

    /**
     * 传输信息，必须是json格式， JWT里面保存的用户信息
     */

    @Setter
    private String msg;
    /**
     * 所验证的jwt  产生的JWT字符串
     */
    @Setter
    private String token;


    public JwtTokenServiceImpl() {
    }

    public JwtTokenServiceImpl(String msg, String token) {
        this.msg = msg;
        this.token = token;
    }


    // 秘钥
    private final String secret = "324iu23094u598ndsofhsiufhaf_+0wq-42q421jiosadiusadiasd";


    public static void main(String[] args) {

////        // 创建一个JWT
////        JwtTokenUtils jwtTokenUtils = new JwtTokenUtils();
////        jwtTokenUtils.setMsg("王二狗");
////
////        String token = jwtTokenUtils.creatJwtToken();
////        System.out.println("产生的token:" +token);
//
//
////        JwtTokenUtils jwtTokenUtils = JwtTokenUtils.builder().msg("songgeniupi").build();
////
////        String token = jwtTokenUtils.creatJwtToken();
////
////        System.out.println("token:" + token);
//        //eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjaWdnYXIiLCJleHAiOjE2MDgzNDk3MDIsInVzZXIiOiIzNTZFODY2NkFDMDAzQzU4NjNFREUzOTc1N0VGRDVEMSJ9.fSSWJMni5Y5dEdbSXh8-7ONVtUgl7U3B4fW7oKclOcs


        JwtTokenServiceImpl jwtTokenUtils = JwtTokenServiceImpl.builder().token("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjaWdnYXIiLCJleHAiOjE2MDgzNDk3MDIsInVzZXIiOiIzNTZFODY2NkFDMDAzQzU4NjNFREUzOTc1N0VGRDVEMSJ9.fSSWJMni5Y5dEdbSXh8-7ONVtUgl7U3B4fW7oKclOcs")
                .build();

        String msg = jwtTokenUtils.freeJwt();

        System.out.println("获取到的信息: " + msg);

    }

    // 创建JWT的方法
    public String creatJwtToken() {
        msg = new AESUtil(msg).encrypt();//先对信息进行aes加密(防止被破解） AES 对称加密
        String token = null;
        try {
            token = JWT.create()
                    .withIssuer("ciggar").withExpiresAt(DateTime.now().plusDays(1).toDate())
                    .withClaim("user", msg)
                    .sign(Algorithm.HMAC256(secret));
        } catch (Exception e) {
            throw e;
        }
        log.info("加密后：" + token);
        return token;
    }

    /**
     * 解密jwt并验证是否正确
     */
    public String freeJwt() {
        DecodedJWT decodedJWT = null;
        try {
            //使用hmac256加密算法
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret))
                    .withIssuer("ciggar")
                    .build();
            decodedJWT = verifier.verify(token);
            log.info("签名人：" + decodedJWT.getIssuer() + " 加密方式：" + decodedJWT.getAlgorithm() + " 携带信息：" + decodedJWT.getClaim("user").asString());
        } catch (Exception e) {
            log.info("jwt解密出现错误，jwt或私钥或签证人不正确");
            throw new ValidateException(SysRetCodeConstants.TOKEN_VALID_FAILED.getCode(), SysRetCodeConstants.TOKEN_VALID_FAILED.getMessage());
        }
        //获得token的头部，载荷和签名，只对比头部和载荷
        String[] headPayload = token.split("\\.");
        //获得jwt解密后头部
        String header = decodedJWT.getHeader();
        //获得jwt解密后载荷
        String payload = decodedJWT.getPayload();
        if (!header.equals(headPayload[0]) && !payload.equals(headPayload[1])) {
            throw new ValidateException(SysRetCodeConstants.TOKEN_VALID_FAILED.getCode(), SysRetCodeConstants.TOKEN_VALID_FAILED.getMessage());
        }
        return new AESUtil(decodedJWT.getClaim("user").asString()).decrypt();
    }

    @Override
    public Long getUserInfo(String access_token) {
        setToken(access_token);
        String userTokenJson = freeJwt();
        JSONObject jsonObject = JSON.parseObject(userTokenJson);
        long uid = Long.parseLong(jsonObject.getString("uid"));
        return uid;
    }
}
